<?php

namespace common\service;

use malkusch\lock\mutex\PHPRedisMutex;
use support\bootstrap\Redis;
use support\SingletonTrait;

/**
 * 会话最后更新时间服务
 */
class ChatEditedAtUpdateService
{

    // 单例工具类
    use SingletonTrait;

    protected $queueSetName = 'chat_modify_time:queue_set';
    protected $messageDataHashPrefix = 'chat_modify_time:message_data:';
    protected $messageDataLockKeyPrefix = 'chat_modify_time_update:';

    /**
     * 推送更新编辑时间事件
     * @param $chatId
     * @param $editedAt
     * @param $xu
     * @return mixed
     * @throws \Exception
     */
    public function pushUpdateEvent($chatId, $editedAt, $xu)
    {
        $mutex = new PHPRedisMutex([Redis::connection()->client()], $this->messageDataLockKeyPrefix . $chatId, 3);
        return $mutex->synchronized(function () use ($chatId, $editedAt, $xu) {
            // 检查hashtable里的编辑时间和要更新的时间是否一样
            $dataKey = $this->messageDataHashPrefix . $chatId;
            $currentEditedAt = Redis::hGet($dataKey, 'edited_at');
            if (intval($currentEditedAt) === $editedAt) {
                // 无需修改
                return false;
            }
            // 检查当前是否在队列里面
            $exist = Redis::sAdd($this->queueSetName, $chatId);

            // 设置要更新的数据和更新标志
            Redis::hSet($dataKey, 'edited_at', $editedAt);
            Redis::hSet($dataKey, 'saved', 'no');
            Redis::hSet($dataKey, 'xu', $xu);
            return $exist != 0;
        });
    }

    /**
     * 取出需要更新的事件
     * @return mixed|null[]
     * @throws \Exception
     */
    public function pullUpdateEvent($chatId)
    {
        // 弹出右侧队首
        $mutex = new PHPRedisMutex([Redis::connection()->client()], $this->messageDataLockKeyPrefix . $chatId, 3);
        return $mutex->synchronized(function () use ($chatId) {
            // 取出event_data
            $editedAt = Redis::hGet($this->messageDataHashPrefix . $chatId, 'edited_at');
            $xu = Redis::hGet($this->messageDataHashPrefix . $chatId, 'xu');
            // 标记取出过
            Redis::hSet($this->messageDataHashPrefix . $chatId, 'saved', 'yes');
            // 设置缓存过期时间 无操作 4小时销毁
            Redis::expire($this->messageDataHashPrefix . $chatId, 60 * 60 * 4);
            // 去除队列唯一存在标记
            Redis::sRem($this->queueSetName, $chatId);
            return [$chatId, $editedAt, $xu];
        });

    }
}
